package com.sy.simpleegg.platform.whm

import android.content.Context
import android.util.Log
import com.sy.simpleegg.platform.whm.bean.MqttData
import com.sy.simpleegg.platform.whm.bean.WhmGoodBean
import com.sy.simpleegg.platform.whm.cmd.CmdAssistant
import com.sy.simpleegg.platform.whm.cmd.CmdProducter
import com.sy.simpleegg.platform.whm.service.TimingService
import com.sy.simpleegg.platform.whm.service.TqMqttService
import com.sy.simpleegg.platform.whm.util.DESUtil
import com.sy.simpleegg.util.GsonUtil
import com.sy.logger.Logger
import java.math.BigDecimal
import java.math.RoundingMode

class WhmMqtt(
    private val devNumber: String,
    private val devTypeMq: String,
    private val ver: String,
    private val context: Context,
){
    private val TAG = javaClass.simpleName

    private val CMD_LOGIN = "02"
    private val CMD_DEV_INIT = "04"
    private val CMD_HEART_BEAT = "06"
    private val CMD_ORDER = "70"
    private val CMD_PACKAGE = "008B"
    private val CMD_BACKSCAN = "000B"
    private val CMD_BILL = "008D"
    private val CMD_ORDER_VER2 = "0080"
    private val CMD_PAY_CODE = "000D"
    private val CMD_TIPS = "000E"
    private val CMD_WITHDRAWAL_CODE = "008F"

    private var packageRequestCount: Long = 0

    private var packageNormalList: MutableList<WhmGoodBean> = mutableListOf()
    private var packageRechargeList: MutableList<WhmGoodBean> = mutableListOf()

    private var onMqttDataCallback: OnMqttDataCallback? = null

    init {
        try {
            TqMqttService.setParams(devTypeMq, devNumber, ver);
            TqMqttService.setMqttData(object : MqttData {
                override fun onResult(topic: String?, json: String?) {
                    topic?.let {
                        when {
                            it.contains("/GXC02") -> {
                                doVersion2(json!!)
                            }

                            it.contains("/GXC01") -> {
                                doVersion1(json)
                            }
                        }
                    }
                }

                override fun onTopicSuccess() {
                    //主题订阅成功，开始登录
                    onMqttDataCallback?.toLogin()
                }

                override fun connect(connectState: Boolean) {
                    onMqttDataCallback?.connectionChange(connectState)
                }

            });
            TqMqttService.startService(context);//开启服务
            TimingService.startService(context);
        }catch (e: Exception){
            e.printStackTrace()
            log("mqtt异常：${e.message}")
        }
    }

    fun publish(protocolVer: String, msg: ByteArray) {
        TqMqttService.publish(protocolVer, msg)
    }

    private fun doVersion1(json: String?){
        try {
            val head = json!!.substring(0, 2)
            if ("EC" != head) {
                Logger.d("接收的消息异常:数据头 ！= EC $json")
                return
            }
            val len = json!!.substring(2, 4).toInt(16)
            val bodyEncrypt = json!!.substring(4)
            if (len * 2 != bodyEncrypt.length) {
                Logger.d("doVersion1()接收的消息异常:数据包不完整 $json")
                return
            }

            val decryptData = DESUtil.decode2(MQConfig.DEV_KEY, bodyEncrypt)
            Logger.d("mqtt_onresult: \n加密数据=$bodyEncrypt \n解密数据=$decryptData")

            parseData1(decryptData)
        }catch (e: Exception){
            e.printStackTrace()
            log("doVersion1()异常:${e.message}")
        }
    }

    private fun parseData1(data: String){
        try {
            //取命令号，应答的命令号 = 命令号 + 1
            val cmdFlag = data.substring(6, 8)

            when (cmdFlag) {
                CMD_LOGIN -> {
                    val loginState = data.substring(24, 26)
                    loginEvent(loginState)
                }

                CMD_DEV_INIT -> {}
                CMD_HEART_BEAT -> Logger.d("收到服务器心跳响应：$data")
                CMD_ORDER -> {}
                CMD_PACKAGE -> {}
                else -> {}
            }
        }catch (e: Exception){
            e.printStackTrace()
            log("parseData1()异常：${e.message}")
        }
    }

    private fun loginEvent(state: String){
        try {
            when (state) {
                "00" -> {
                    Logger.d("登录成功")
                    onMqttDataCallback?.onLoginSuccess()
                }

                "01" -> {
                    Logger.d("登录失败")
                    onMqttDataCallback?.reLogin()
                }

                "02" -> Logger.d("设备禁用")
                "03" -> Logger.d("账号密码错误")
                "04" -> Logger.d("设备未注册")
                else -> {}
            }
        }catch (e: Exception){
            e.printStackTrace()
            log("loginEvent()异常：${e.message}")
        }
    }

    private fun doVersion2(data: String){
        try {
            //取命令号，应答的命令号 = 命令号 + 1
            val cmdFlag: String = data.substring(6, 10)
            when (cmdFlag) {
                CMD_PACKAGE -> {
                    Log.d("SyMqttCallback", "收到套餐数据：$data")
                    try {
                        var packageCount = 0
                        if (data.substring(16, 20) == "0000") {
                            Log.d("SyMqttCallback", "获取套餐数量：" + data.substring(14, 16))
                            val packageType: Int = data.substring(12, 14).toInt(16)
                            //获取套餐总数
                            packageCount = CmdAssistant.calculateHex(data.substring(14, 16))
                            if (packageCount > 0) {
                                //发送消息，获取所有套餐
                                onMqttDataCallback?.getPackage(packageCount, packageType)
                            } else {
                                if (packageType == MQConfig.PACKAGE_TYPE_NORMAL) {
                                    Log.d("SyMqttCallback", "packageCount <= 0")
                                    onMqttDataCallback?.getPackage(0, MQConfig.PACKAGE_TYPE_RECHARGE)
                                } else if (packageType == MQConfig.PACKAGE_TYPE_RECHARGE) {
                                    if (packageNormalList.size > 0) {
                                        //套餐数据持久化
//                                        val date = Date()
//                                        val entity = PackageEntity()
//                                        entity.date = DateUtil.getDate(date)
//                                        entity.time = DateUtil.getDate2(date)
//                                        val beanList: ArrayList<GoodBean> = ArrayList()
//                                        beanList.addAll(packageNormalList)
//                                        entity.detail = beanList
//                                        DBManager.insertPackage(entity).doOnSuccess { aLong ->
//                                            Log.d("SyMqttCallback", "插入套餐数据2=$aLong")
//                                            packageNormalList = ArrayList()
//                                            onMqttDataCallback?.refreshPackageData()
//
//                                        }.subscribe()

                                        val pkgList = packageNormalList
                                        packageNormalList = mutableListOf()
                                        onMqttDataCallback?.refreshPackageData(pkgList)
                                    } else {
                                        onMqttDataCallback?.refreshPackageData(mutableListOf())
                                        Logger.d("两种套餐的套餐数都是0")
                                    }
                                }
                            }
                        } else {
                            val packageType: Int = data.substring(12, 14).toInt(16)
                            val packageData: String = data.substring(20)
                            //                        Logger.d("套餐数据：" + packageData);
                            if (packageType == MQConfig.PACKAGE_TYPE_NORMAL) {
                                packageNormalList = ArrayList()
                                val dataItemLen = 223 * 2
                                var i = 0
                                while (i < packageData.length / dataItemLen) {
                                    val itemData = packageData.substring(
                                        i * dataItemLen,
                                        (i + 1) * dataItemLen
                                    )
                                    val id = itemData.substring(0, 8)
                                    val nameHex = splitZeroRight(itemData.substring(8, 68))
                                    val name = CmdAssistant.hexStringToString(nameHex)
                                    val urlHex = splitZeroRight(itemData.substring(68, 428))
                                    val url = CmdAssistant.hexStringToString(urlHex)
                                    val amountStr = itemData.substring(428, 434)
                                    val amount = CmdAssistant.calculateHex(splitZeroLeft(amountStr)!!)
                                    val a = BigDecimal.valueOf(amount.toFloat().toDouble())
                                    a.setScale(2, RoundingMode.HALF_UP)
                                    val realAmountStr = itemData.substring(434, 440)
                                    val realAmount =
                                        CmdAssistant.calculateHex(splitZeroLeft(realAmountStr)!!)
                                    val R = BigDecimal.valueOf(realAmount.toFloat().toDouble())
                                    R.setScale(2, RoundingMode.HALF_UP)
                                    val coinCountStr = itemData.substring(440, 446)
                                    val coinCount =
                                        CmdAssistant.calculateHex(splitZeroLeft(coinCountStr)!!)
                                    val bean = WhmGoodBean(
                                        id,
                                        packageType,
                                        realAmount.toString(),
                                        coinCount.toString(),
                                        "",
                                        "0",
                                        name?:"",
                                        url?:"",
                                        amount.toString(),
                                        ""
                                    )
                                    packageNormalList.add(bean)
                                    Logger.d(
                                        "普通套餐项：" +
                                                "\nid=" + id +
                                                "\nname=" + name +
                                                "\nurl=" + url +
                                                "\namount=" + amount +
                                                "\nralAmount=" + realAmount +
                                                "\ncoin=" + coinCount
                                    )
                                    i++
                                }
                                //获取套餐类型2的套餐数据
                                onMqttDataCallback?.getPackage(0, MQConfig.PACKAGE_TYPE_RECHARGE)
                                Logger.d(
                                    "普通套餐数据:" + GsonUtil.getInstance()!!
                                        .toJson(packageNormalList)
                                )
                            } else if (packageType == MQConfig.PACKAGE_TYPE_RECHARGE) {
                                packageRechargeList = java.util.ArrayList()
                                val dataItemLen = 223 * 2
                                var i = 0
                                while (i < packageData.length / dataItemLen) {
                                    val itemData = packageData.substring(
                                        i * dataItemLen,
                                        (i + 1) * dataItemLen
                                    )
                                    val id = itemData.substring(0, 8)
                                    val nameHex = splitZeroRight(itemData.substring(8, 68))
                                    val name = CmdAssistant.hexStringToString(nameHex)
                                    val urlHex = splitZeroRight(itemData.substring(68, 428))
                                    val url = CmdAssistant.hexStringToString(urlHex)
                                    val amountStr = itemData.substring(428, 434)
                                    val amount = CmdAssistant.calculateHex(splitZeroLeft(amountStr)!!)
                                    val a = BigDecimal.valueOf(((amount).toFloat()).toDouble())
                                    a.setScale(2, RoundingMode.HALF_UP)
                                    val realAmountStr = itemData.substring(434, 440)
                                    val realAmount =
                                        CmdAssistant.calculateHex(splitZeroLeft(realAmountStr)!!)
                                    val R = BigDecimal.valueOf(((realAmount).toFloat()).toDouble())
                                    R.setScale(2, RoundingMode.HALF_UP)
                                    val coinCountStr = itemData.substring(440, 446)
                                    val coinCount =
                                        CmdAssistant.calculateHex(splitZeroLeft(coinCountStr)!!)
                                    val bean = WhmGoodBean(
                                        id,
                                        packageType,
                                        realAmount.toString(),
                                        coinCount.toString(),
                                        "",
                                        "0",
                                        name?:"",
                                        url?:"",
                                        amount.toString(),
                                        ""
                                    )
                                    packageRechargeList.add(bean)
                                    Logger.d(
                                        ("充值套餐项：" +
                                                "\nid=" + id +
                                                "\nname=" + name +
                                                "\nurl=" + url +
                                                "\namount=" + amount +
                                                "\nralAmount=" + realAmount +
                                                "\ncoin=" + coinCount)
                                    )
                                    i++
                                }
                                Logger.d(
                                    "充值套餐数据:" + GsonUtil.getInstance()!!
                                        .toJson(packageRechargeList)
                                )

                                //套餐数据持久化
//                                val date = Date()
//                                val entity = PackageEntity()
//                                entity.date = DateUtil.getDate(date)
//                                entity.time = DateUtil.getDate2(date)
                                val beanList: MutableList<WhmGoodBean> = mutableListOf()
                                Log.d(
                                    "SyMqttCallback",
                                    "packageNormalList.size() = " + packageNormalList.size
                                )
                                if (packageNormalList.size > 0) {
                                    beanList.addAll(beanList.size, packageNormalList)
                                }
                                beanList.addAll(beanList.size, packageRechargeList)
//                                entity.detail = beanList
//                                Logger.d("最终套餐数据:" + GsonUtil.getInstance().toJson(beanList))
//                                DBManager.insertPackage(entity).doOnSuccess { aLong ->
//                                    Log.d("SyMqttCallback", "插入套餐数据=$aLong")
//                                    packageNormalList = ArrayList()
//                                    packageRechargeList = ArrayList()
//                                    onMqttDataCallback?.refreshPackageData()
//                                }.subscribe()

                                packageNormalList = mutableListOf()
                                packageRechargeList = mutableListOf()
                                onMqttDataCallback?.refreshPackageData(beanList)
                            }
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                        Logger.e("套餐数据处理异常：" + e.message)
                    }
                }

                CMD_BACKSCAN -> try {
                    val responState: String = data.substring(data.length - 2)
                    if (("00" == responState)) {
                        Logger.d("收到反扫响应成功")
                    } else {
                        Logger.d("收到反扫响应异常：$responState")
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                    Logger.e("反扫响应数据处理异常：" + e.message)
                }

                CMD_BILL -> try {
                    val billRespons: String = data.substring(data.length - 2)
                    if (("00" == billRespons)) {
                        Logger.d("收到投钞响应成功")
                        val billMsgNumber: String = data.substring(data.length - 4, data.length - 2)
                        onMqttDataCallback?.onBillResponse(true, billMsgNumber)
                    } else {
                        Logger.d("收到投钞响应异常：$billRespons")
                    }
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                    Logger.e("投钞响应数据处理异常：" + e.message)
                }

                CMD_ORDER_VER2 -> try {
                    val orderNumberHex: String = data.substring(10, 74)
                    val temp = splitZeroRight(orderNumberHex)
                    val orderNumberByteArr = CmdAssistant.hexToByteArray(temp!!)
                    val orderNumber = String(orderNumberByteArr!!) //订单号
                    val outCountHex: String = data.substring(74, 80) //出币数量
                    val payType: String = data.substring(80, 82) //兑币方式
                    val amountHex: String = data.substring(82, 88) //订单金额
                    //                        String amount = CmdAssistant.hexToStr(amountHex);
                    val remainHex: String = data.substring(88, 94) //账户余额
                    //                        String remain = CmdAssistant.hexToStr(remainHex);
                    var accountRemainCoinHex = "00"
                    if (("51" == payType)) {
                        accountRemainCoinHex = data.substring(94, 100) //会员账户币数余额
                    }
//                    val now = Date()
//                    val orderEntity = OrderEntity()
//                    orderEntity.date = DateUtil.getDate(now)
//                    orderEntity.time = DateUtil.getDate2(now)
//                    orderEntity.onDutyCode = Constants.ONDUTY_CODE
//                    orderEntity.orderNumber = orderNumber
//                    orderEntity.success = 0
//                    orderEntity.inCoin = 0
//                    orderEntity.payType = payType.toInt(16)
//                    orderEntity.outCoin = outCountHex.toInt(16).toLong()
//                    orderEntity.amount = amountHex.toInt(16).toString()
//                    orderEntity.remainAmount = remainHex.toInt(16).toString()
//                    orderEntity.accountRemainCoin = accountRemainCoinHex.toInt(16)
//                    Logger.d("收到订单：" + GsonUtil.getInstance()!!.toJson(orderEntity))
                    onMqttDataCallback?.receiveOrder(
                        amountHex.toInt(16).toString(),
                        outCountHex.toInt(16).toString(),
                        orderNumber,
                        payType.toInt(16),
                        remainHex.toLong(16).toString(),
                        accountRemainCoinHex.toLong(16).toString()
                    )
                } catch (e: Exception) {
                    e.printStackTrace()
                    Logger.e("收到订单通知，解析异常：" + e.message)
                }

                CMD_PAY_CODE -> try {
                    val payCodeHex: String = data.substring(12)
                    val payCodeByteArr = CmdAssistant.hexToByteArray(payCodeHex)
                    val payCodeData = String(payCodeByteArr!!)
                    Logger.d("支付二维码数据：$payCodeData")
                    onMqttDataCallback?.showPayCode(payCodeData, 0)
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                    Logger.e("支付二维码，解析异常：" + e.message)
                }

                CMD_TIPS -> try {
//                    onMqttDataCallback?.responseTips()
                    respTips()
                    val colorHex: String = data.substring(48, 50) //颜色
                    val contentHex: String = data.substring(50)
                    val contentByteArr = CmdAssistant.hexToByteArray(contentHex)
                    val tips = String(contentByteArr!!)
                    Logger.d("收到提示信息：$tips")
                    onMqttDataCallback?.showTips(colorHex.toInt(16), tips)
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                    Logger.e("收到提示信息，解析异常：" + e.message)
                }

                CMD_WITHDRAWAL_CODE -> try {
                    val withdrawalCodeHex: String = data.substring(10)
                    val withdrawalCodeByteArr = CmdAssistant.hexToByteArray(withdrawalCodeHex)
                    val withdrawalCodeData = String(withdrawalCodeByteArr!!)
                    Logger.d("会员提币码数据：$withdrawalCodeData")
                    onMqttDataCallback?.showPayCode(withdrawalCodeData, 1)
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                    Logger.e("收到提示信息，解析异常：" + e.message)
                }

                else -> {}
            }
        } catch (e: Exception) {
            e.printStackTrace()
            Logger.e(e, "解析消息异常:$data")
        }
    }

    private fun respTips() {
        val tipsRepMsg = CmdProducter.tipsRep
        log("获取提示信息上报：" + CmdAssistant.byteArrayToHexStr(tipsRepMsg))
        publish(MQConfig.PROTOCOL_VER2, tipsRepMsg!!)
    }

    private fun splitZeroLeft(hexStr: String): String? {
        var result = hexStr
        try {
            while (result.length > 2 && result.substring(0, 2) == "00") {
                result = result.substring(2)
            }
        }catch (e: Exception){
            e.printStackTrace()
            log("删除左边的0异常：${e.message}")
        }
        return result
    }

    private fun splitZeroRight(hexStr: String): String? {
        var result = hexStr
        try {
            while (result.length > 2 && result.substring(
                    result.length - 2,
                    result.length
                ) == "00"
            ) {
                result = result.substring(0, result.length - 2)
            }
        }catch (e: Exception){
            e.printStackTrace()
            log("删除右边的0异常：${e.message}")
        }
        return result
    }

    /**
     * 获取支付二维码
     */
    fun getPayCode(pkgId: Int, payType: Int, pkgType: Int){
        val payCodeMsg = CmdProducter.getPayCode(pkgId, payType, pkgType)
        Logger.d("获取支付二维码数据：" + CmdAssistant.byteArrayToHexStr(payCodeMsg))
        publish(MQConfig.PROTOCOL_VER2, payCodeMsg!!)
    }

    interface OnMqttDataCallback{
        /**
         * 订阅主题成功，执行登录指令
         */
        fun toLogin()

        /**
         * 链接状态改变
         * @param connectState 链接状态
         */
        fun connectionChange(connectState: Boolean)

        /**
         * 重新登录
         */
        fun reLogin()

        /**
         * 登录成功
         */
        fun onLoginSuccess()

        /**
         * 获取套餐
         * @param pkgCount 套餐数量 0-获取套餐数量 >0-套餐内容的套餐数
         * @param pkgType 套餐类型
         */
        fun getPackage(pkgCount: Int, pkgType: Int)

        /**
         * 刷新套餐数据
         */
        fun refreshPackageData(dataList: MutableList<WhmGoodBean>)

        /**
         * 投钞响应
         * @param sucess
         * @param billMsgNumber 消息编号
         */
        fun onBillResponse(sucess: Boolean, billMsgNumber: String)

        /**
         * 收到订单数据
         * @param orderEntity 订单实体
         * @param msg
         */
//        fun receiveOrder(orderEntity: OrderEntity, msg: String?)
        fun receiveOrder(money: String, coins: String, k: String, type: Int, accountMoney: String, accountCoins: String)

        /**
         * 显示二维码
         * @param payCodeData 二维码内容
         * @param type 显示类型 0-二维码 1-图片
         */
        fun showPayCode(payCodeData: String, type: Int)

        /**
         * 响应收到提示信息
         */
        fun responseTips()

        /**
         * 显示提示
         * @param color 1-黑色 其他-红色
         * @param tips 内容
         */
        fun showTips(color: Int, tips: String)
    }

    fun setCallback(callback: OnMqttDataCallback){
        onMqttDataCallback = callback
    }

    private fun log (msg: String){
        Log.d(TAG, msg)
        Logger.d(msg)
    }
}